#ifndef __AFXTLS_H__
#define __AFXTLS_H__
#include <windows.h>
#include <stddef.h>

//class CNoTrackObject;
class CSimpleList
{
public:
	CSimpleList(int nNextOffset=0);
	void Construct(int nNextOffset);

	BOOL IsEmpty() const;
	void AddHead(void* p);
	void RemoveAll();
	void* GetHead() const;
	BOOL Remove(void *p);
	void* GetNext(void* p) const;
	void* m_pHead;
	size_t m_nNextOffset;
	void **GetNextPtr(void* p) const;
};


template<class TYPE>
class CTypedSimpleList:public CSimpleList
{
public:
	CTypedSimpleList(int nNextOffest=0):CSimpleList(nNextOffest){}
	void AddHead(TYPE p)
	{
		CSimpleList::AddHead((void*)p);
	}

	TYPE GetHead()
	{
		return (TYPE)CSimpleList::GetHead();
	}
	TYPE GetNext(TYPE p)
	{
		return (TYPE)CSimpleList::GetNext(p);
	}
	BOOL Remove(TYPE p)
	{
		return CSimpleList::Remove(p);
	}
	operator TYPE()
	{
		return (TYPE)CSimpleList::GetHead();
	}
};

class CNoTrackObject
{
public:
	void* operator new(size_t nSize);
	void operator delete(void*);
	virtual ~CNoTrackObject(){}
};
#pragma warning(disable : 4291) 
struct CSlotData;
struct CThreadData;
class CThreadSlotData
{
public:
	CThreadSlotData();
	int AllocSlot();
	void FreeSlot(int nSlot);
	void* GetThreadValue(int nSlot);
	void SetValue(int nSlot,void* pValue);
	void DeleteValue(HINSTANCE hInst,BOOL bAll=FALSE);
	DWORD m_tlsIndex;
	int m_nAlloc;
	int m_nRover;
	int m_nMax;
	CSlotData* m_pSlotData;
	CTypedSimpleList<CThreadData*>m_list;
	CRITICAL_SECTION m_cs;
	void* operator new(size_t,void*p){return p;}
	void DeleteValues(CThreadData* pData,HINSTANCE hInst);
	void DeleteValues(HINSTANCE hIns,BOOL bAll);
	~CThreadSlotData();
};

class CThreadLocalObject
{
public:
	CNoTrackObject* GetData(CNoTrackObject* (*pfnCreateObject)());
	CNoTrackObject* GetDataNA();
	DWORD m_nSlot;
	~CThreadLocalObject();

};

template<class TYPE>
class CThreadLocal : public CThreadLocalObject
{
public:
	/*static CNoTrackObject* CreateObject()
	{
		TYPE *p = new TYPE;
		return (CNoTrackObject*)p ;
	}*/

	TYPE* GetData()
	{
		TYPE* pData = (TYPE*)CThreadLocalObject::GetData(&CreateObject);
		return pData;
	}

	TYPE* GetDataNA()
	{
		TYPE* pData = (TYPE*)CThreadLocalObject::GetDataNA();
		return pData;
	}

	operator TYPE*()
	{
		return GetData();
	}
	TYPE* operator->()
	{
		return GetData();
	}
public:
	static CNoTrackObject* CreateObject()
	{ return new TYPE; }
	
};

#define THREAD_LOCAL(class_name,ident_name) CThreadLocal<class_name>ident_name;

#define EXTERN_THREAD_LOCAL(class_name, ident_name) extern THREAD_LOCAL(class_name,ident_name)
#endif